local Entity = class("Entity")
local Attributes = require("gameLogic.fightEntity.Attributes")
local FightSkill = require("gameLogic.fight.fightSkill.FightSkill")
local Signal = require("event.Signal")
local AttributeConst = require("const.AttributeConst")

function Entity:ctor(excuter, normalSkillCfg, id, element)
    assert(excuter, "can not nil excuter")
    self._excuter = excuter
    self._id = id
    self._actionEndsignal = Signal.new()
    self._baseAttr = Attributes.new()
    self._sheildMaps = {}
    self._skills = {}
    self._sheilds = {}
    self._feature = {sex = 0, race = 0}
    self._isDie = false
    self._element = element or 0
    self:addNormalSkill(normalSkillCfg)
end

function Entity:getClassName()
    return self.__cname
end

function Entity:isFight()
    return true
end

function Entity:setFeature(peo) -- 设置他作为生物的特征
    self._feature = peo
end

function Entity:getFeature()
    return self._feature
end

function Entity:registerEntityActionEvent(callback, once)
    self._actionEndsignal:registerListener(callback, 1, once)
end

function Entity:dispatchActionEnd()
    self._actionEndsignal:dispatch("actionEnd")
end

function Entity:getElement()
    return self._element
end

function Entity:getId()
    return self._id
end

function Entity:initFightAttr(attr)
    self._baseAttr:setPureAttr(attr)
end

function Entity:setDebugName(name)
    self._debugName = name
end

function Entity:getDebugName()
    return self._debugName
end

function Entity:addCounterattackSkill(skillConfig)
    self._counterattackSKill = FightSkill.new(skillConfig, self)
end

function Entity:addSheild(sheild, battleReport)
    sheild:setEntity(self)
    local oldSheild = self._sheildMaps[sheild:getId()]
    if not oldSheild then
        self._sheildMaps[sheild:getId()] = sheild
    else
        oldSheild:changeValue(sheild:getValue())
    end
    battleReport:addSheild(sheild, self)
end

function Entity:removeSheild(id, battleReport)
    if self._sheildMaps[id] then
        self._sheildMaps[id]:remove(battleReport)
        self._sheildMaps[id] = nil
    end
end

function Entity:getAttrValue(id)
    local baseValue = self._baseAttr:getAttrValue(id)
    return baseValue
end

function Entity:setDie(die)
    self._isDie = die
    if self._isDie then
        local buffManager = self:getExcuter():getBuffManager()
        buffManager:removeBuffByEntity(self)
        printDebug(self:getDebugName() .. " 死亡")
    end
end

function Entity:isDie()
    return self._isDie
end

-- 设置占位(行列)
function Entity:setStanding(stand)
    self._stand = stand
end

-- 设置阵营（1-甲方，2-乙人）
function Entity:setCamp(camp)
    self._camp = camp
end

function Entity:getExcuter()
    return self._excuter
end

function Entity:getCamp()
    return self._camp
end

function Entity:getStandRow()
    return self._stand.row
end

function Entity:getStandCol()
    return self._stand.col
end

function Entity:setBehavior(behavior)
    self._behavior = behavior
    self._behavior:setEntity(self)
end

function Entity:getBehavior()
    return self._behavior
end

-- 普攻技能
function Entity:addNormalSkill(skillConfig)
    if not skillConfig then
        return
    end
    local skill = require("gameLogic.fight.fightSkill.FightSkill").new(skillConfig, self)
    self._normalSkill = skill
end

-- 后天技能
function Entity:addSkill(skillConfig)
    if not skillConfig then
        return
    end
    local skill = require("gameLogic.fight.fightSkill.FightSkill").new(skillConfig, self)
    skill:setStunt(true)
    table.insert(self._skills, skill)
end

function Entity:subSkillCooling()
    if not self._skills then
        return
    end
    for i = 1, #self._skills do
        self._skills[i]:subSkillCooling()
    end
end

function Entity:action(battleReport)
    if self:isDie() then
        return
    end
    Entity:subSkillCooling()
    battleReport:addAttackEntity(self)
    printDebug("行为逻辑：" .. self._behavior:getName())
    self._behavior:excute(battleReport)
end

function Entity:getSkills()
    return self._skills
end

function Entity:getAllSkills()
    local result = {}
    table.insert(result, self._normalSkill)
    for i = 1, #self._skills do
        table.insert(result, self._skills[i])
    end
    return result
end

function Entity:getSkillById(id)
    for i = 1, #self._skills do
        if self._skills[i]:getId() == id then
            return self._skills[i]
        end
    end
    return self._normalSkill
end

function Entity:getNormalSKill()
    return self._normalSkill
end

function Entity:getEnemys()
    return self._excuter:getEnemys(self._camp)
end

function Entity:getFriends()
    return self._excuter:getFriends(self._camp)
end

--被造成伤害
function Entity:beHurt(hurt, battleReport)
    if self:isDie() then
        return
    end
    local reportAttackTime = battleReport:newAttackTime(self:getId())
    G_SignalManager:dispatch(SignalConst.EVENT_ENTITY_HURT_TIME, self:getId(), hurt, reportAttackTime)
    self:simpleHurt(hurt, reportAttackTime)
    battleReport:addHurt(hurt, self)
    self:_counterattack(hurt, battleReport)
end

function Entity:simpleHurt(hurt, battleReport)
    local AttributeConst = require("const.AttributeConst")
    if hurt.element == AttributeConst.ELEMENT_TREATMENT then
        printDebug(self:getDebugName() .. " 获得治疗 " .. (hurt.value))
        local blood = self:getAttrValue(AttributeConst.BLOOD)
        blood = blood + hurt.value
        self:_setAttrValue(AttributeConst.BLOOD, blood)
        self:setDie(blood <= 0)
    else
        local retHurt = self:_checkSheild(hurt, battleReport)
        printDebug(self:getDebugName() .. " 受到伤害 " .. retHurt)
        local blood = self:getAttrValue(AttributeConst.BLOOD)
        blood = blood - retHurt
        self:_setAttrValue(AttributeConst.BLOOD, blood)
        G_SignalManager:dispatch(SignalConst.EVENT_ENTITY_HURT, self:getId(), battleReport)
        self:setDie(self:getAttrValue(AttributeConst.BLOOD) <= 0) --可能其他地方属性变化
    end
end

function Entity:hurtBefore(battleReport)
    local FightConst = require("const.FightConst")
    local report = battleReport:newHurtBefore(self:getId())
    local buffManager = self._excuter:getBuffManager()
    buffManager:checkBuffExcuteByEffectTime(FightConst.BUFF_BE_HURT_B, self, report)
end

function Entity:hurtAfter(battleReport, hurt)
    local FightConst = require("const.FightConst")
    local report = battleReport:newHurtAfter(self:getId())
    local buffManager = self._excuter:getBuffManager()
    buffManager:checkBuffExcuteByEffectTime(FightConst.BUFF_BE_HURT_A, self, report)
end

function Entity:optAttrValue(attrId, value)
    if self:isDie() then
        return
    end
    assert(attrId ~= AttributeConst.BLOOD)
    self:_setAttrValue(attrId, value)
end

function Entity:_checkSheild(hurt, battleReport)
    if hurt.ignoreSheid then
        return hurt.value
    end
    local minHurt = hurt.value
    for id, sheild in pairs(self._sheildMaps) do
        local retHurt = sheild:beAttack(hurt.value, hurt.element)
        if sheild:isBroken() then
            G_SignalManager:dispatch(SignalConst.EVENT_ENTITY_SHEILD_BROKEN, self:getId(), battleReport)
            self:removeSheild(id, battleReport)
        end
        hurt:setAbsorb(true)
        minHurt = math.min(retHurt, minHurt)
        hurt.value = minHurt
    end
    return minHurt
end

function Entity:noDie() -- 免死
    self._baseAttr:setAttrValue(AttributeConst.BLOOD, 1)
end

function Entity:_setAttrValue(id, value)
    self._baseAttr:setAttrValue(id, value)
end

function Entity:getBaseAttrValue(id)
    return self._baseAttr:getBaseAttrValue(id)
end

function Entity:getFakeAttrValue(id)
    return self._baseAttr:getFakeAttrValue(id)
end

function Entity:setFakeAttrValue(id, value)
    assert(id ~= AttributeConst.BLOOD)
    self._baseAttr:setFakeAttrValue(id, value)
end

function Entity:getAttrs()
    return self._baseAttr:getContent()
end

function Entity:_counterattack(hurt, battleReport)
    if self:isDie() then
        return
    end
    if not hurt.entityId then
        return
    end
    local counterattack = self:getAttrValue(AttributeConst.COUNTERATTACK)
    local pro = math.random(1, 1000)
    if pro <= counterattack then
        local report = battleReport:newHurtAfter(self:getId())
        local tarEntity = self._excuter:getEntityById(hurt.entityId)
        local hurts = self._normalSkill:pureAct({tarEntity})
        report:addCounterAttack(hurts[1], self, tarEntity, self._normalSkill:getId())
    end
end

return Entity
